#include <bits/stdc++.h>
using namespace std;

static inline uint64_t rng64() {
    static thread_local uint64_t x = chrono::high_resolution_clock::now().time_since_epoch().count();
    x ^= x << 7; x ^= x >> 9; x ^= x << 8;
    return x;
}
static inline uint64_t rng64_seeded(uint64_t &s) {
    s ^= s << 7; s ^= s >> 9; s ^= s << 8;
    return s;
}

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    // 参数解析
    long long n = 2e5, m = 2e5;
    long long maxA = 1000, maxX = 1000;
    int queryRatio = 3; // 生成操作2的比例(百分比)
    bool hasSeed = false;
    uint64_t seed = 0;

    if (argc >= 3) {
        n = atoll(argv[1]);
        m = atoll(argv[2]);
    }
    if (argc >= 4) maxA = atoll(argv[3]);
    if (argc >= 5) maxX = atoll(argv[4]);
    if (argc >= 6) queryRatio = atoi(argv[5]);
    if (argc >= 7) { hasSeed = true; seed = strtoull(argv[6], nullptr, 10); }
    if (queryRatio < 0) queryRatio = 0;
    if (queryRatio > 100) queryRatio = 100;

    uint64_t s = hasSeed ? seed : rng64();

    // 限制与安全检查
    n = max(1LL, min(n, (long long)5e5));
    m = max(1LL, min(m, (long long)5e5));
    maxA = max(1LL, min(maxA, (long long)1e9));
    maxX = max(1LL, min(maxX, (long long)1e9));

    // 生成初始数组
    vector<long long> a(n + 1);
    for (int i = 1; i <= n; ++i) {
        // 保证 >=1
        a[i] = (long long)(rng64_seeded(s) % maxA) + 1;
    }

    // 打印 n, m
    cout << n << ' ' << m << '\n';
    // 打印 a
    for (int i = 1; i <= n; ++i) {
        if (i > 1) cout << ' ';
        cout << a[i];
    }
    cout << '\n';

    const long long MOD = (1LL << 20) - 1; // 用于 sum mod 2^20（通过按位与实现）
    long long lastans = 0; // 初始为 0

    auto rand_between = [&](long long L, long long R) -> long long {
        if (L > R) swap(L, R);
        uint64_t span = (uint64_t)(R - L + 1);
        return (long long)(rng64_seeded(s) % span) + L;
    };

    for (long long opi = 1; opi <= m; ++opi) {
        bool isQuery = ((int)(rng64_seeded(s) % 10) < queryRatio);

        if (!isQuery) {
            // 操作 1：1 l r x
            long long L = rand_between(1, n);
            long long R = rand_between(1, n);
            long long X = rand_between(1, maxX);

            // 随机制造一部分 l>r 的输入，评测会自己规范化
            if(L>R)swap(L,R);

            // 按真实参数执行更新（朴素线性）
            int l0 = (int)min(L, R), r0 = (int)max(L, R);
            for (int i = l0; i <= r0; ++i) if (a[i] > X) a[i] -= X;

            // 打印时需与当前 lastans 异或
            long long outL = L/* ^ lastans*/;
            long long outR = R/* ^ lastans*/;
            long long outX = X/* ^ lastans*/;
            cout << "1 " << outL << ' ' << outR << ' ' << outX << '\n';
        } else {
            // 操作 2：2 l r
            long long L = rand_between(1, n);
            long long R = rand_between(1, n);
            if(L>R)swap(L,R);

            int l0 = (int)min(L, R), r0 = (int)max(L, R);

            long long sumv = 0;
            long long mnv = (long long)4e18;
            long long mxv = -(long long)4e18;

            for (int i = l0; i <= r0; ++i) {
                sumv += a[i];
                if (a[i] < mnv) mnv = a[i];
                if (a[i] > mxv) mxv = a[i];
            }

            // 更新 lastans（sum mod 2^20）
            long long new_last = sumv & MOD;
            lastans = new_last;

            long long outL = L /*^ (lastans)*/; // 注意：与题意一致，输入 l,r 要与“上一次询问的 lastans”异或。
            long long outR = R /*^ (lastans)*/;

            cout << "2 " << outL << ' ' << outR << '\n';
            // 说明：生成器只输出输入文件，不打印答案行
        }
    }

    return 0;
}
